package hu.myai.triggers.bullish;

import hu.myai.api.tick.AbstractTickProvider;
import hu.myai.api.triggers.AbstractTrigger;
import hu.myai.indicators.LowerBollingerIndicator;
import hu.myai.indicators.pivot.LastHighIndicator;
import hu.myai.indicators.tick.TickIndicator;
import hu.myai.indicators.tick.TickVolumeChangeIndicator;
import hu.myai.model.IndicatorVO;
import hu.myai.model.TriggerVO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 1. Stock is moving (falling) with lower bollinger.<br/>
 * 2. Take a rest and pull back<br/>
 * 3. The stock is falling again but separatly from the bollinger<br/>
 * 4. high volume turns the down trend<br/>
 * 5. major pullback is expected that goes to the upper bowlinger<br/>
 * TODO test with real data
 * 
 * @author bozbalint
 * 
 * */

public class LowerBollingerAndVolumeTrigger extends AbstractTrigger {

	Double firstBollingerValue;

	Double firstTickValue;

	int stage = 0;

	int firstTickCounter = 0;

	int secondTickCounter = 0;

	/**
	 * The object used when logging debug,errors,warnings and info.
	 * */
	private final Logger log = LoggerFactory.getLogger(this.getClass());

	public LowerBollingerAndVolumeTrigger(String name, AbstractTickProvider tick) {
		super(name, tick);
	}

	private String lowBollingerID;

	public void setLowerBollingerIndicatorParameter(double parameter) {
		lowBollingerID = register(new LowerBollingerIndicator(parameter));
	}

	private String lastHighID;

	public void setLastHighIndicatorParameter(double parameter) {
		lastHighID = register(new LastHighIndicator(parameter));
	}

	private String tickID;

	public void setTickIndicatorParameter() {
		tickID = register(new TickIndicator(TickIndicator.CLOSE));
	}

	private String volumeID;

	public void setVolumeChangeIndicator() {
		volumeID = register(new TickVolumeChangeIndicator());
	}

	@Override
	protected TriggerVO triggerCalculation() {

		IndicatorVO secondBollingerIndicator = indicatorMap.get(lowBollingerID);
		IndicatorVO secondLastHighIndicator = indicatorMap.get(lastHighID);
		IndicatorVO secondTickIndicator = indicatorMap.get(tickID);
		IndicatorVO secondVolumeChangeIndicator = indicatorMap.get(volumeID);

		// ignore calculation if no indicator value
		if (secondBollingerIndicator == null || secondLastHighIndicator == null || secondTickIndicator == null
				|| secondVolumeChangeIndicator == null) {
			return null;
		}

		// Skip calculation while this class history is not set properly
		if (firstBollingerValue == null || firstTickValue == null) {

			firstBollingerValue = secondBollingerIndicator.getValue();
			firstTickValue = secondTickIndicator.getValue();

			return null;
		}

		firstTickCounter++;

		// the stock is moving down with the bollinger band
		if (stage == 0 && (firstTickValue / firstBollingerValue < 1.03)
				&& (secondTickIndicator.getValue() / secondBollingerIndicator.getValue() < 1.03)) {
			stage = 1;
			firstTickCounter = 0;
		}

		// pull back
		if (stage == 1 && secondLastHighIndicator.isChanged()) {
			stage = 2;
			secondTickCounter = firstTickCounter;
		}

		TriggerVO trigger = null;

		if (stage == 2 && secondVolumeChangeIndicator.getValue() > 2) {

			stage = 0;
			trigger = new TriggerVO();
			trigger.setTick(lastTick);
			trigger.setRisk(20);
			trigger.setTradeType(TriggerVO.BUY_ONMARKET);

			log.debug(trigger.toString());
			return trigger;

		}

		if (secondTickCounter > firstTickCounter * 1.5 || (stage == 2 && secondLastHighIndicator.isChanged())) {
			stage = 0;
		}

		firstBollingerValue = secondBollingerIndicator.getValue();
		firstTickValue = secondTickIndicator.getValue();

		return trigger;
	}
}
